/**
 * @{# File.java Create on 2008-12-9 下午04:34:36
 * 
 *     Copyright (c) 2008 by HandPay.
 */
package com.handpay.framework;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import se.krka.kahlua.vm.LuaTable;
import se.krka.kahlua.vm.LuaTableImpl;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Environment;

/**
 * @author <a href="mailto:justin.hou@handpay.com.cn">Sora</a>
 * @version 1.0
 */
public final class FileUtil
{
	private static String rootPath=null;
	// 得到路径中的path
	private static String getFileDir(String path){
		String[] split=path.split("/");
		String rpath="";
		if(split!=null && split.length>1){
			for(int i=0;i<split.length-1;i++){
				rpath=rpath+split[i]+"/";
			}
		}
		return 	rpath;
	}
	public static Boolean saveFile(byte[] data, String path){
		File file = new File(path);
		File dir = new File(getFileDir(path));
		DataOutputStream write_stream = null;
		try {
			if (!dir.exists()) {
				if (!dir.mkdirs()) {
					return false;
				}
			}
			if (!file.exists()) {
				if (!file.createNewFile()) {
					return false;
				}
			}
			/*if (file.exists()) {
				file.delete();
			}
			if (!file.createNewFile()) {
					return false;
			}*/
			write_stream = new DataOutputStream(new FileOutputStream(file,
					false));
			write_stream.write(data);
			return true;
		} catch (Exception e) {
			return false;
		} finally {
			if (write_stream != null) {
				try {
					write_stream.close();
				} catch (Exception e) {
				}
			}
		}
	}
	public static byte[] readFile(String path) {
		byte[] data = null;
		File file = new File(path);
		if (file.exists()&& !file.isDirectory()) {
			DataInputStream read_stream =null;
			try {
				int filelenght = (int) file.length();
				data = new byte[filelenght];
				read_stream = new DataInputStream(
						new FileInputStream(file));
				read_stream.read(data);
			} catch (Exception e) {
				data = null;
			}finally{
				if(read_stream!=null){
					try{
						read_stream.close();
					}catch(Exception e){}
				}
			}

		}
		return data;
	}
	// 检查外设是否可用
	static private boolean externalMemoryAvailable() {
		return android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED);
	}
	private static String GetRealHeader(Context context){
		if (rootPath == null) {
			boolean is_phone = true;
			File path = null;
			if (is_phone) {
				
				if (context != null) {
					path = context.getFilesDir();
					String pathname = path.getAbsolutePath();
					if (!pathname.substring(pathname.length() - 1,
							pathname.length()).equals("/")) {
						pathname = pathname + "/";
					}
					rootPath = pathname;
				}
			}else{
		    	if(externalMemoryAvailable()){
		    		path = Environment.getExternalStorageDirectory();
					String pathname=path.getAbsolutePath();
					if(!pathname.substring(pathname.length()-1, pathname.length())
							.equals("/")){
						pathname=pathname+"/";
					}   		
					rootPath = pathname; 		
		    	}
			}
		}
		String rp=rootPath;
		if(rp==null){
			rp="";
		}
		return rp;
	}
	
	
	/**
	 * 判断文件是否存在。
	 * 
	 * @param path
	 *            文件地址。
	 * @return 如果存在则返回true，否则返回false。
	 */
	public static boolean exists(String path)
	{
			File file=new File(path);
			return  file.exists();
	}
	
	private static void delectfile(File file){
		if(file.exists()){
			if(file.isFile()){
				file.delete();
			}else if(file.isDirectory()){
				File[] dirlist= file.listFiles() ;
				if(dirlist!=null){
					for(int i=0;i<dirlist.length;i++){
						delectfile(dirlist[i]);
					}
				}
				file.delete();
			}
		}
	}
	
	/**
	 * 删除文件。
	 * 
	 * @param path
	 *            文件地址。
	 */
	public static boolean delete(String path)
	{
			File file=new File(path);
			delectfile(file);
			return true;
	}
	
	public static String getRealUrl(Context context,String path){
		String header=FileUtil.GetRealHeader(context);
		path=header+path;
		return path;
	}
	
	public static String getRealUrl(Context context,String path,byte type){
		String header=FileUtil.GetRealHeader(context);
		switch(type){
			case HandPayPath.PATH_FILE:
				path=header+"handpay/file/"+path;
				break;
			case HandPayPath.PATH_CACHE:
				path=header+"handpay/cache/"+path;
				break;
			case HandPayPath.PATH_TEMP:	
				path=header+"handpay/temp/"+path;
				break;
		}
		return path;
	}
	
	public static boolean CreatDir(String path){
		File dir = new File(path);
		boolean suc=false;
		try {
			if (!dir.exists()) {
				if (dir.mkdirs()) {
					suc=true;
				}
			}
		}catch(Exception e){
			suc=false;
		}
		return suc;
	}
	public static boolean fileExists(String url) {
		File conn = new File(url);
		boolean result = conn.exists();
		return result;
	}
	public static boolean fileRename(String oldurl,String newurl){
		File oldfile = new File(oldurl);
		if(oldfile.exists()&& !oldfile.isDirectory()){
			File newfile = new File(newurl);
			File dir = new File(getFileDir(newurl));
			if (!dir.exists()) {
				if (!dir.mkdirs()) {
					return false;
				}
			}
			return oldfile.renameTo(newfile);
		}
		return false;
	}
	
	public static File CreatFile(String path){
		File file = new File(path);  
        try
		{
			file.createNewFile();
		}
		catch (IOException e)
		{
			return null;
		}  
        return file; 
	}
	
	public static long copy(InputStream input, OutputStream output) throws IOException {
		byte[] buffer = new byte[1024 * 4];
		long count = 0;
		int n = 0;
		while (-1 != (n = input.read(buffer))) {
			output.write(buffer, 0, n);
			count += n;
		}
		output.flush();
		return count;
	}
	
	/**
	 * 将一个InputStream里面的数据写入到SD卡中
	 * 
	 * @param path
	 * @param fileName
	 * @param input
	 * @return
	 */ 
   public static File write2SDFromInput(String path,String fileName,InputStream input){  
       File file = null;  
       OutputStream output = null;  
       try {  
       	CreatDir(path);  
           file = CreatFile(path + fileName);  
           output = new FileOutputStream(file);  
           byte[] buffer = new byte[1024];  
           while((input.read(buffer)) != -1){  
               output.write(buffer);  
           }  
           output.flush();  
       }   
       catch (Exception e) {  
           e.printStackTrace();  
       }  
       finally{  
           try {  
               output.close();  
           } catch (IOException e) {  
               e.printStackTrace();  
           }  
       }  
       return file;  
   }
   
   public static boolean unZipFile(File zipfile, String destDir) {
	   byte b[] = new byte [1024];
       int length;
 
       ZipFile zipFile;
       try {
           zipFile = new ZipFile(zipfile);
           Enumeration<?> enumeration = zipFile.entries();
           ZipEntry zipEntry = null ;
 
           while (enumeration.hasMoreElements()) {
              zipEntry = (ZipEntry) enumeration.nextElement();
              File loadFile = new File(destDir + zipEntry.getName());
 
              if (zipEntry.isDirectory()) {
            	// 这段都可以不要，因为每次都貌似从最底层开始遍历的
                  loadFile.mkdirs();
              } else {
                  if (!loadFile.getParentFile().exists())
                     loadFile.getParentFile().mkdirs();
 
                  OutputStream outputStream = new FileOutputStream(loadFile);
                  InputStream inputStream = zipFile.getInputStream(zipEntry);
 
                  while ((length = inputStream.read(b)) > 0)
                     outputStream.write(b, 0, length);
                  outputStream.close();
              }
           }
           return true;
       } catch (IOException e) {
           e.printStackTrace();
       }
	   
	   return false;
   }
   
	public static boolean makeDir(String unZipDir) {
		boolean b = false;
		try {
			File f = new File(unZipDir);
			if (!f.exists()) {
				b = f.mkdirs();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return b;
		}
		return b;
	}
   
	/**
	 * 解压一个压缩文档文件流 到指定位置
	 * 
	 * @param stream
	 * @param outPathString
	 * @return
	 */
   public static boolean UnZipFolder(InputStream stream, String outPathString)
   {  
   	
       try
		{ 
			ZipInputStream inZip = new ZipInputStream(stream);  
			ZipEntry zipEntry;  
			String szName = "";  
			  
			while ((zipEntry = inZip.getNextEntry()) != null) {  
			    szName = zipEntry.getName();
//			    Log.e("UnZipFolder", szName);
			  
			    int index = szName.indexOf(File.separator);
			    if (zipEntry.isDirectory()) {  
			  
			        // get the folder name of the widget  
			        szName = szName.substring(0, szName.length() - 1);  
			        File folder = new File(outPathString + File.separator + szName);  
			        folder.mkdirs();  
			  
			    }
			    else
			    {  
			    	if(index > 0 && index < szName.length())
				    {
				    	String folderName = szName.substring(0,index);
				    	File folder = new File(outPathString + File.separator + folderName);  
				        folder.mkdirs();
				    }
			        File file = new File(outPathString + File.separator + szName);  
			        file.createNewFile();  
			        // get the output stream of the file  
			        FileOutputStream out = new FileOutputStream(file);  
			        int len;  
			        byte[] buffer = new byte[1024];  
			        // read (len) bytes into buffer  
			        while ((len = inZip.read(buffer)) != -1) {  
			            // write (len) byte from buffer at the position 0  
			            out.write(buffer, 0, len);  
			            out.flush();  
			        }  
			        out.close();  
			    }  
			}//end of while  
			  
			inZip.close();
			
			return true;
		}
		catch (Exception e)
		{
			return false;
		}  
     
   }
   
   /**
	 * 解压一个压缩文档 到指定位置
	 * 
	 * @param zipFileString
	 *            压缩包的名字
	 * @param outPathString
	 *            指定的路径
	 * @throws Exception
	 */ 
   public static boolean UnZipFolder(String zipFileString, String outPathString)
   {  
   	
       try
		{
			ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));  
			ZipEntry zipEntry;  
			String szName = "";  
			  
			while ((zipEntry = inZip.getNextEntry()) != null) {  
			    szName = zipEntry.getName();
//			    Log.e("UnZipFolder", szName);
			  
			    int index = szName.indexOf(File.separator);
			    if (zipEntry.isDirectory()) {  
			  
			        // get the folder name of the widget  
			        szName = szName.substring(0, szName.length() - 1);  
			        File folder = new File(outPathString + File.separator + szName);  
			        folder.mkdirs();  
			  
			    }
			    else
			    {  
			    	if(index > 0 && index < szName.length())
				    {
				    	String folderName = szName.substring(0,index);
				    	File folder = new File(outPathString + File.separator + folderName);  
				        folder.mkdirs();
				    }
			        File file = new File(outPathString + File.separator + szName);  
			        file.createNewFile();  
			        // get the output stream of the file  
			        FileOutputStream out = new FileOutputStream(file);  
			        int len;  
			        byte[] buffer = new byte[1024];  
			        // read (len) bytes into buffer  
			        while ((len = inZip.read(buffer)) != -1) {  
			            // write (len) byte from buffer at the position 0  
			            out.write(buffer, 0, len);  
			            out.flush();  
			        }  
			        out.close();  
			    }  
			}//end of while  
			  
			inZip.close();
			
			return true;
		}
		catch (Exception e)
		{
			return false;
		}  
     
   }
   
   public static InputStream getISFromPackage(Context context,String url){
		AssetManager assetm=context.getAssets();
		if (assetm!=null){
			InputStream stream=null;
			try{
				int start=0;
				if(url.startsWith("/")){
					start=1;
				}
				stream=assetm.open(url.substring(start));
				if (stream != null){
					return stream;
				}
			}catch(Exception e){
				return null;
			}
		}
		return null;
	}
   
   public static HandPayPath TreatPath(String path){
		String[] items=path.split("/");
		HandPayPath rdata=new HandPayPath();
		if(items!=null && items.length>0){
			boolean isMark=false;
			for(int i=0;i<items.length;i++){
				if(items[i].indexOf("res:")>=0){
					if(!isMark){
						isMark=true;
						rdata.type=HandPayPath.PATH_RES;
					}
					continue;
				}else if(items[i].indexOf("file:")>=0){
					if(!isMark){
						isMark=true;
						rdata.type= HandPayPath.PATH_FILE;
					}
					continue;
				}else if(items[i].indexOf("cache:")>=0){
					if(!isMark){
						isMark=true;
						rdata.type=HandPayPath.PATH_CACHE;
					}
					continue;
				}else if(items[i].indexOf("memory:")>=0){
					if(!isMark){
						isMark=true;
						rdata.type=HandPayPath.PATH_MEMORY;
					}
					continue;
				}else if(items[i].indexOf("tmp:")>=0){
					rdata.type=HandPayPath.PATH_TEMP;
					continue;
				}else if(items[i].indexOf("/")>=0){
					continue;
				}else if(items[i].trim().compareTo("")!=0){
					if(rdata.path==null){
						rdata.path=items[i];
					}else{
						rdata.path=rdata.path+"/"+items[i];
					}
				}
			}
		}
		return rdata;
	}
   
   /**
	 * 获得所有磁盘根目录名称。
	 * 
	 * @return 所有磁盘根目录的名称。
	 */
	public static String[] getAllRoots()
	{
		Vector<String> roots = new Vector<String>();
		File path=null;
		
		Context context=ClientEngine.getInstance().getActivity();
		if(context!=null){
			path=context.getFilesDir();
			String pathname=path.getAbsolutePath();
			if(!pathname.substring(pathname.length()-1, pathname.length())
					.equals("/")){
				pathname=pathname+"/";
			}	
       	roots.add(pathname);			
		}

   	if(externalMemoryAvailable()){
   		path = Environment.getExternalStorageDirectory();
			String pathname=path.getAbsolutePath();
			if(!pathname.substring(pathname.length()-1, pathname.length())
					.equals("/")){
				pathname=pathname+"/";
			}   		
       	roots.add(pathname);

       	//Caojun 3/11
       	File root = new File(pathname);
       	File files[] = root.listFiles();
       	for (File f : files)
       	{
       		if (!f.isDirectory())
   			{
   				continue;
   			}
       		pathname=f.getAbsolutePath();
   			if(!pathname.substring(pathname.length()-1, pathname.length())
   					.equals("/")){
   				pathname=pathname+"/";
   			} 
       		roots.add(pathname);
       	}
   	}
   	
   	//Caojun 12/21
   	File ext = new File("/mnt/sdcard-ext/");
   	if(ext.exists())
   	{
   		roots.add("/mnt/sdcard-ext/");
   	}
   	
		String[] strRoots = null;
		if(roots.size()>0){
			strRoots=new String[roots.size()];
			roots.copyInto(strRoots);			
		}
		return strRoots;
	}
	
	private static void getFiles(String dir,boolean IncludeDir,
			Vector<filedata>files,Vector<String>dirs,String backpath){
		File path=new File(dir);
		if(path.exists()&& path.isDirectory()){
			File[] dirlist= path.listFiles() ;
			for(int i=0;i<dirlist.length;i++){
				String rname=dir+"/"+dirlist[i].getName();
				String bname=null;
				if(backpath==null){
					bname=dirlist[i].getName();
				}else{
					bname=backpath+"/"+dirlist[i].getName();
				}
				if(dirlist[i].isFile()){
					filedata fileitem=new filedata();
					fileitem.name=bname;
					fileitem.size=dirlist[i].length();
					files.add(fileitem);
				}else if(dirlist[i].isDirectory()){
					if(IncludeDir){	
						getFiles(rname,IncludeDir,
								files,dirs,bname);
					}else{
						dirs.add(dirlist[i].getName());
					}
				}
			}
		}
	}
	
	private static class filedata{
		String name;
		long size;
	}
	/**
	 * 获得目录下面的所有文件。
	 * 
	 * @param path
	 *            目录地址。
	 * @param filter
	 *            过滤器。
	 * @return 所有文件的名称。
	 */
	public static LuaTable getFiles(String path, boolean IncludeDir) {
		Vector<filedata> files=new Vector<filedata>();
		Vector<String> dirs=new Vector<String>();
		
		getFiles(path,IncludeDir,files,dirs,null);
		
		LuaTable resultdata=new LuaTableImpl();
		LuaTable filedata=new LuaTableImpl();
		LuaTable dirdata=new LuaTableImpl();
		
		for(int i=0;i<files.size();i++){
			filedata fitem=files.elementAt(i);
			LuaTable fitemt=new LuaTableImpl();
			fitemt.rawset(1, fitem.name);
			fitemt.rawset(2, Double.valueOf(fitem.size));	
			filedata.rawset(i+1, fitemt);
		}
		for(int i=0;i<dirs.size();i++){
			String temdir= dirs.elementAt(i);
			dirdata.rawset(i+1, temdir);
		}
		resultdata.rawset("file", filedata);
		resultdata.rawset("dir", dirdata);	
		return resultdata;
	}
}
